﻿using CCB_B2CPay_Util;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityPay.Core.DTO;
using UnityPay.Core.PayBase;
using UnityPay.Core.Utils;
namespace UnityPay.Core.BankClass
{
    public class CCB : BankBaseClass, BankPayActionInterface
    {
        #region 构造函数
        public CCB(string pubkey,string branchid,string merchantid,string posid, string ip ="127.0.0.1" ,int prot=9999, string groupmch="")
        {
            this.PubKey = pubkey;
            this.BRANCHID = branchid;
            this.MERCHANTID = merchantid;
            this.POSID = posid;
            this.GROUPMCH = groupmch;
            this.Url = "https://ibsbjstar.ccb.com.cn/CCBIS/B2CMainPlat_00_BEPAY?";
            sc = new SocketUtil(ip, prot);
        }
        public SocketUtil sc;
        #endregion

        #region 建设银行请求需要的通用参数参数
        /// <summary>
        /// 分行号
        /// 必输入
        /// </summary>
        public string BRANCHID { get; set; }

        /// <summary>
        /// 柜台号
        /// 必输入
        /// </summary>
        public string POSID { get; set; }
        /// <summary>
        /// 集团商户信息
        /// 非必要
        /// </summary>
        public string GROUPMCH { get; set; } = "";
        /// <summary>
        /// 加密串
        /// 比输入
        /// </summary>
        public string ccbParam { get; set; }


        #endregion

        
        #region Pay参数
        private string TXCODE { get; set; }
        private string MERFLAG { get; set; } = "1";
        private string TERMNO1 { get; set; }
        private string TERMNO2 { get; set; }
        private string REMARK1 { get; set; }
        private string REMARK2 { get; set; }
        #endregion

        #region 返回参数



        #endregion

        #region 支付方法

        public override string GetUrl()
        {
            return Url+ $"MERCHANTID={MERCHANTID}&POSID={POSID}&BRANCHID={BRANCHID}&GROUPMCH={GROUPMCH}&ccbParam=";
        }
        public virtual BankMsgDTO Pay(string amount, string qrcode, string orderid,  string goodsname="")
        {
            TXCODE = "PAY100";
            string param = $"TXCODE={TXCODE}&MERFLAG={MERFLAG}&TERMNO1={TERMNO1}&TERMNO2={TERMNO2}&ORDERID={orderid}&QRCODE={qrcode}&AMOUNT={amount}&PROINFO={goodsname}&REMARK1={REMARK1}&REMARK2={REMARK2}";
            string actionUrl = GetUrl()  + GetccbParam(param);
            string res = HttpUtil.HttpSend(actionUrl);
            return JsonConvert.DeserializeObject<BankMsgDTO>(res);
        }

        public virtual BankMsgDTO Query(string orderid, string qrcodetype)
        {
            TXCODE = "PAY101";
            string param = $@"TXCODE={TXCODE}&MERFLAG={MERFLAG}&TERMNO1={TERMNO1}&TERMNO2={TERMNO2}&ORDERID={orderid}&QRYTIME=1&QRCODETYPE={qrcodetype}&REMARK1={REMARK1}&REMARK2={REMARK2}";
            string actionUrl = GetUrl() + GetccbParam(param);
            string res = HttpUtil.HttpSend(actionUrl);
            return JsonConvert.DeserializeObject<BankMsgDTO>(res);

        }



        public virtual BankMsgDTO ZfbWxQuery(string orderid, string qrcodetype)
        {
            TXCODE = "PAY102";
            string param = $@"TXCODE={TXCODE}&MERFLAG={MERFLAG}&TERMNO1={TERMNO1}&TERMNO2={TERMNO2}&ORDERID={orderid}&QRCODETYPE={qrcodetype}";
            string actionUrl = GetUrl() + GetccbParam(param);
            string res = HttpUtil.HttpSend(actionUrl);
            return JsonConvert.DeserializeObject<BankMsgDTO>(res);
        }
        public virtual BankMsgDTO ZfbWxOrderClose(string orderid, string qrcodetype)
        {
            TXCODE = "PAY103";
            string param = $@"TXCODE={TXCODE}&MERFLAG={MERFLAG}&TERMNO1={TERMNO1}&TERMNO2={TERMNO2}&ORDERID={orderid}&QRCODETYPE={qrcodetype}";
            string actionUrl = GetUrl() + GetccbParam(param);
            string res = HttpUtil.HttpSend(actionUrl);
            return JsonConvert.DeserializeObject<BankMsgDTO>(res);
        }
        string RefundMsg;
        //退款方式返回暂定
        public virtual string Refund(string CUST_ID,string USER_ID,string PASSWORD, string orderid, string amount, string Refundid)
        {
            try
            {
                StringBuilder sb = new StringBuilder("");
                sb.Append(@"<?xml version=" + "\"1.0" + "\" encoding=\"GB2312\" standalone=\"yes\" ?>");
                sb.Append("<TX>");
                sb.Append($"<REQUEST_SN>{DateTime.Now.ToString("yyyyMMddHHmmss")}</REQUEST_SN>");
                sb.Append($"<CUST_ID>{CUST_ID}</CUST_ID>");
                sb.Append($"<USER_ID>{USER_ID}</USER_ID>");
                sb.Append($"<PASSWORD>{PASSWORD}</PASSWORD>");
                sb.Append("<TX_CODE>5W1004</TX_CODE>");
                sb.Append("<LANGUAGE>CN</LANGUAGE>");
                sb.Append("<TX_INFO>");
                sb.Append($"<MONEY>{amount}</MONEY>");
                sb.Append($"<ORDER>{orderid}</ORDER>");
                sb.Append($"<REFUND_CODE>{Refundid}</REFUND_CODE>");
                sb.Append("</TX_INFO>");
                sb.Append("<SIGN_INFO></SIGN_INFO>");
                sb.Append("<SIGNCERT></SIGNCERT>");//Socker自动补充
                sb.Append("</TX>");
                sc.StartClient();
                //sc.ReceiveMessageEvent += RefundResEvent;
                //Encoding.GetEncoding("GB2312").GetBytes(sb.ToString());
                sc.SendMessage(Encoding.GetEncoding("GB2312").GetBytes(sb.ToString()));//GetEncoding("GB2312")
                var data = sc.ReceiveMessage(sc._socket);
                return RefundMsg = Encoding.GetEncoding("GB2312").GetString(data);
                //return RefundMsg.XmlStrToObject<TX>();
            }
            catch (Exception)
            {

                throw;
            }

        }
        /// <summary>
        /// 返回退货信息
        /// </summary>
        /// <returns></returns>
        public string GetRefund() { return RefundMsg; }
        public void RefundResEvent(object o, EventArgs e)
        {
            RefundMsg = "";
            byte[] data = (byte[])o;
            RefundMsg = Encoding.GetEncoding("GB2312").GetString(data);
            Console.WriteLine(RefundMsg);
        }
        #endregion
        private string GetccbParam(string source,string key="")
        {
            string encryptionStr = "";
            if (!string.IsNullOrEmpty(this.PubKey))
            {
                 encryptionStr = new CCBPayUtil().makeCCBParam(source, this.PubKey);
            }
            if (!string.IsNullOrEmpty(key))
            {
                encryptionStr = new CCBPayUtil().makeCCBParam(source, key);
            }
            return encryptionStr;
        }

        public BankMsgDTO IcbcRefund(string orderid, string amount, string Refundid)
        {
            throw new Exception("建行不支持工商银行退款接口");
        }

        public BankMsgDTO IcbcRefundQuery(string orderid, string Refundid)
        {
            throw new Exception("建行不支持工商银行退款查询接口");
        }
    }
    /// <summary>
    /// 建设银行支付
    /// </summary>
    public class CCBPay : CCB
    {
        #region 基础参数设置
        /// <summary>
        /// 建设银行支付
        /// </summary>
        /// <param name="BRANCHID">分行号</param>
        /// <param name="MERCHANTID">商户号</param>
        /// <param name="POSID">柜台号</param>
        /// <param name="PubKey">公钥</param>
        public CCBPay(string BRANCHID,string MERCHANTID,string POSID,string PubKey,string IP="127.0.0.1",int PROT=9991)
            :base(PubKey,BRANCHID,MERCHANTID,POSID,IP,PROT)
        {
        }
        #endregion
    }
    public class RefundMsg
    {
        public TX TX{ get; set; }
    }
    public class TX
    {
        public string REQUEST_SN { get; set; }

        public string CUST_ID { get; set; }

        public string TX_CODE { get; set; }

        public string RETURN_CODE { get; set; }
        public string RETURN_MSG { get; set; }
        public string LANGUAGE { get; set; }
        public TX_INFO TX_INFO { get; set; }
    }
    public class TX_INFO
    {
        public string ORDER_NUM { get; set; }
        public string PAY_AMOUNT { get; set; }
        public string AMOUNT { get; set; }
        public string REM1 { get; set; }
        public string REM2 { get; set; }
    }

}
